package com.bird.common.utils.tkmybatis;

import tk.mybatis.mapper.weekend.Fn;
import tk.mybatis.mapper.weekend.WeekendCriteria;
import tk.mybatis.mapper.weekend.reflection.Reflections;

import java.util.Arrays;
import java.util.Map;

/**
 * 包装tk mybatis的查询类，一行代码搞定
 *
 * @author: 625
 * @version: 2020年06月09日 14:54
 */
public class TKCriteria<A, B> extends WeekendCriteria<A, B> {

	private TK<A> queryTK;

	protected TKCriteria(Map propertyMap, boolean exists, boolean notNull, TK<A> queryTK) {
		super(propertyMap, exists, notNull);
		this.queryTK = queryTK;
	}

	@Override
	public TKCriteria<A, B> andIsNull(Fn<A, B> fn) {
		this.andIsNull(Reflections.fnToFieldName(fn));
		return this;
	}

	public TKCriteria<A, B> andIsNull(boolean condition, Fn<A, B> fn) {
		if (condition) {
			this.andIsNull(Reflections.fnToFieldName(fn));
		}
		return this;
	}

	@Override
	public TKCriteria<A, B> andIsNotNull(Fn<A, B> fn) {
		super.andIsNotNull(Reflections.fnToFieldName(fn));
		return this;
	}

	public TKCriteria<A, B> andIsNotNull(boolean condition, Fn<A, B> fn) {
		if (condition) {
			super.andIsNotNull(Reflections.fnToFieldName(fn));
		}
		return this;
	}

	@Override
	public TKCriteria<A, B> andEqualTo(Fn<A, B> fn, Object value) {
		super.andEqualTo(Reflections.fnToFieldName(fn), value);
		return this;
	}

	public TKCriteria<A, B> andEqualTo(boolean condition, Fn<A, B> fn, Object value) {
		if (condition) {
			super.andEqualTo(Reflections.fnToFieldName(fn), value);
		}
		return this;
	}

	@Override
	public TKCriteria<A, B> andNotEqualTo(Fn<A, B> fn, Object value) {
		super.andNotEqualTo(Reflections.fnToFieldName(fn), value);
		return this;
	}

	public TKCriteria<A, B> andNotEqualTo(boolean condition, Fn<A, B> fn, Object value) {
		if (condition) {
			super.andNotEqualTo(Reflections.fnToFieldName(fn), value);
		}
		return this;
	}

	@Override
	public TKCriteria<A, B> andGreaterThan(Fn<A, B> fn, Object value) {
		super.andGreaterThan(Reflections.fnToFieldName(fn), value);
		return this;
	}

	public TKCriteria<A, B> andGreaterThan(boolean condition, Fn<A, B> fn, Object value) {
		if (condition) {
			super.andGreaterThan(Reflections.fnToFieldName(fn), value);
		}
		return this;
	}

	@Override
	public TKCriteria<A, B> andGreaterThanOrEqualTo(Fn<A, B> fn, Object value) {
		super.andGreaterThanOrEqualTo(Reflections.fnToFieldName(fn), value);
		return this;
	}

	public TKCriteria<A, B> andGreaterThanOrEqualTo(boolean condition, Fn<A, B> fn, Object value) {
		if (condition) {
			super.andGreaterThanOrEqualTo(Reflections.fnToFieldName(fn), value);
		}
		return this;
	}

	@Override
	public TKCriteria<A, B> andLessThan(Fn<A, B> fn, Object value) {
		super.andLessThan(Reflections.fnToFieldName(fn), value);
		return this;
	}

	public TKCriteria<A, B> andLessThan(boolean condition, Fn<A, B> fn, Object value) {
		if (condition) {
			super.andLessThan(Reflections.fnToFieldName(fn), value);
		}
		return this;
	}

	@Override
	public TKCriteria<A, B> andLessThanOrEqualTo(Fn<A, B> fn, Object value) {
		super.andLessThanOrEqualTo(Reflections.fnToFieldName(fn), value);
		return this;
	}

	public TKCriteria<A, B> andLessThanOrEqualTo(boolean condition, Fn<A, B> fn, Object value) {
		if (condition) {
			super.andLessThanOrEqualTo(Reflections.fnToFieldName(fn), value);
		}
		return this;
	}

	@Override
	public TKCriteria<A, B> andIn(Fn<A, B> fn, Iterable values) {
		super.andIn(Reflections.fnToFieldName(fn), values);
		return this;
	}

	public TKCriteria<A, B> andIn(boolean condition, Fn<A, B> fn, Iterable values) {
		if (condition) {
			super.andIn(Reflections.fnToFieldName(fn), values);
		}
		return this;
	}

	public TKCriteria<A, B> andIn(Fn<A, B> fn, Object[] values) {
		super.andIn(Reflections.fnToFieldName(fn), Arrays.asList(values));
		return this;
	}

	public TKCriteria<A, B> andIn(boolean condition, Fn<A, B> fn, Object[] values) {
		if (condition) {
			super.andIn(Reflections.fnToFieldName(fn), Arrays.asList(values));
		}
		return this;
	}

	@Override
	public TKCriteria<A, B> andNotIn(Fn<A, B> fn, Iterable values) {
		super.andNotIn(Reflections.fnToFieldName(fn), values);
		return this;
	}

	public TKCriteria<A, B> andNotIn(boolean condition, Fn<A, B> fn, Iterable values) {
		if (condition) {
			super.andNotIn(Reflections.fnToFieldName(fn), values);
		}
		return this;
	}

	public TKCriteria<A, B> andNotIn(Fn<A, B> fn, Object[] values) {
		super.andNotIn(Reflections.fnToFieldName(fn), Arrays.asList(values));
		return this;
	}

	public TKCriteria<A, B> andNotIn(boolean condition, Fn<A, B> fn, Object[] values) {
		if (condition) {
			super.andNotIn(Reflections.fnToFieldName(fn), Arrays.asList(values));
		}
		return this;
	}

	@Override
	public TKCriteria<A, B> andBetween(Fn<A, B> fn, Object value1, Object value2) {
		super.andBetween(Reflections.fnToFieldName(fn), value1, value2);
		return this;
	}

	public TKCriteria<A, B> andBetween(boolean condition, Fn<A, B> fn, Object value1, Object value2) {
		if (condition) {
			super.andBetween(Reflections.fnToFieldName(fn), value1, value2);
		}
		return this;
	}

	@Override
	public TKCriteria<A, B> andNotBetween(Fn<A, B> fn, Object value1, Object value2) {
		super.andNotBetween(Reflections.fnToFieldName(fn), value1, value2);
		return this;
	}

	public TKCriteria<A, B> andNotBetween(boolean condition, Fn<A, B> fn, Object value1, Object value2) {
		if (condition) {
			super.andNotBetween(Reflections.fnToFieldName(fn), value1, value2);
		}
		return this;
	}

	@Override
	public TKCriteria<A, B> andLike(Fn<A, B> fn, String value) {
		super.andLike(Reflections.fnToFieldName(fn), value);
		return this;
	}

	public TKCriteria<A, B> andLike(boolean condition, Fn<A, B> fn, String value) {
		if (condition) {
			super.andLike(Reflections.fnToFieldName(fn), value);
		}
		return this;
	}

	@Override
	public TKCriteria<A, B> andNotLike(Fn<A, B> fn, String value) {
		super.andNotLike(Reflections.fnToFieldName(fn), value);
		return this;
	}

	public TKCriteria<A, B> andNotLike(boolean condition, Fn<A, B> fn, String value) {
		if (condition) {
			super.andNotLike(Reflections.fnToFieldName(fn), value);
		}
		return this;
	}

	@Override
	public TKCriteria<A, B> orIsNull(Fn<A, B> fn) {
		super.orIsNull(Reflections.fnToFieldName(fn));
		return this;
	}

	public TKCriteria<A, B> orIsNull(boolean condition, Fn<A, B> fn) {
		if (condition) {
			super.orIsNull(Reflections.fnToFieldName(fn));

		}
		return this;
	}

	@Override
	public TKCriteria<A, B> orIsNotNull(Fn<A, B> fn) {
		super.orIsNotNull(Reflections.fnToFieldName(fn));
		return this;
	}

	public TKCriteria<A, B> orIsNotNull(boolean condition, Fn<A, B> fn) {
		if (condition) {
			super.orIsNotNull(Reflections.fnToFieldName(fn));
		}
		return this;
	}

	@Override
	public TKCriteria<A, B> orEqualTo(Fn<A, B> fn, Object value) {
		super.orEqualTo(Reflections.fnToFieldName(fn), value);
		return this;
	}

	public TKCriteria<A, B> orEqualTo(boolean condition, Fn<A, B> fn, Object value) {
		if (condition) {
			super.orEqualTo(Reflections.fnToFieldName(fn), value);
		}
		return this;
	}

	@Override
	public TKCriteria<A, B> orNotEqualTo(Fn<A, B> fn, Object value) {
		super.orNotEqualTo(Reflections.fnToFieldName(fn), value);
		return this;
	}

	public TKCriteria<A, B> orNotEqualTo(boolean condition, Fn<A, B> fn, Object value) {
		if (condition) {
			super.orNotEqualTo(Reflections.fnToFieldName(fn), value);
		}
		return this;
	}

	@Override
	public TKCriteria<A, B> orGreaterThan(Fn<A, B> fn, Object value) {
		super.orGreaterThan(Reflections.fnToFieldName(fn), value);
		return this;
	}

	public TKCriteria<A, B> orGreaterThan(boolean condition, Fn<A, B> fn, Object value) {
		if (condition) {
			super.orGreaterThan(Reflections.fnToFieldName(fn), value);
		}
		return this;
	}

	@Override
	public TKCriteria<A, B> orGreaterThanOrEqualTo(Fn<A, B> fn, Object value) {
		super.orGreaterThanOrEqualTo(Reflections.fnToFieldName(fn), value);
		return this;
	}

	public TKCriteria<A, B> orGreaterThanOrEqualTo(boolean condition, Fn<A, B> fn, Object value) {
		if (condition) {
			super.orGreaterThanOrEqualTo(Reflections.fnToFieldName(fn), value);
		}
		return this;
	}

	@Override
	public TKCriteria<A, B> orLessThan(Fn<A, B> fn, Object value) {
		super.orLessThan(Reflections.fnToFieldName(fn), value);
		return this;
	}

	public TKCriteria<A, B> orLessThan(boolean condition, Fn<A, B> fn, Object value) {
		if (condition) {
			super.orLessThan(Reflections.fnToFieldName(fn), value);
		}
		return this;
	}

	@Override
	public TKCriteria<A, B> orLessThanOrEqualTo(Fn<A, B> fn, Object value) {
		super.orLessThanOrEqualTo(Reflections.fnToFieldName(fn), value);
		return this;
	}

	public TKCriteria<A, B> orLessThanOrEqualTo(boolean condition, Fn<A, B> fn, Object value) {
		if (condition) {
			super.orLessThanOrEqualTo(Reflections.fnToFieldName(fn), value);
		}
		return this;
	}

	@Override
	public TKCriteria<A, B> orIn(Fn<A, B> fn, Iterable values) {
		super.orIn(Reflections.fnToFieldName(fn), values);
		return this;
	}

	public TKCriteria<A, B> orIn(boolean condition, Fn<A, B> fn, Iterable values) {
		if (condition) {
			super.orIn(Reflections.fnToFieldName(fn), values);
		}
		return this;
	}

	public TKCriteria<A, B> orIn(Fn<A, B> fn, Object[] values) {
		super.orIn(Reflections.fnToFieldName(fn), Arrays.asList(values));
		return this;
	}

	public TKCriteria<A, B> orIn(boolean condition, Fn<A, B> fn, Object[] values) {
		if (condition) {
			super.orIn(Reflections.fnToFieldName(fn), Arrays.asList(values));
		}
		return this;
	}

	@Override
	public TKCriteria<A, B> orNotIn(Fn<A, B> fn, Iterable values) {
		super.orNotIn(Reflections.fnToFieldName(fn), values);
		return this;
	}

	public TKCriteria<A, B> orNotIn(boolean condition, Fn<A, B> fn, Iterable values) {
		if (condition) {
			super.orNotIn(Reflections.fnToFieldName(fn), values);
		}
		return this;
	}

	public TKCriteria<A, B> orNotIn(Fn<A, B> fn, Object[] values) {
		super.orNotIn(Reflections.fnToFieldName(fn), Arrays.asList(values));
		return this;
	}

	public TKCriteria<A, B> orNotIn(boolean condition, Fn<A, B> fn, Object[] values) {
		if (condition) {
			super.orNotIn(Reflections.fnToFieldName(fn), Arrays.asList(values));
		}
		return this;
	}

	@Override
	public TKCriteria<A, B> orBetween(Fn<A, B> fn, Object value1, Object value2) {
		super.orBetween(Reflections.fnToFieldName(fn), value1, value2);
		return this;
	}

	public TKCriteria<A, B> orBetween(boolean condition, Fn<A, B> fn, Object value1, Object value2) {
		if (condition) {
			super.orBetween(Reflections.fnToFieldName(fn), value1, value2);
		}
		return this;
	}

	@Override
	public TKCriteria<A, B> orNotBetween(Fn<A, B> fn, Object value1, Object value2) {
		super.orNotBetween(Reflections.fnToFieldName(fn), value1, value2);
		return this;
	}

	public TKCriteria<A, B> orNotBetween(boolean condition, Fn<A, B> fn, Object value1, Object value2) {
		if (condition) {
			super.orNotBetween(Reflections.fnToFieldName(fn), value1, value2);
		}
		return this;
	}

	@Override
	public TKCriteria<A, B> orLike(Fn<A, B> fn, String value) {
		super.orLike(Reflections.fnToFieldName(fn), value);
		return this;
	}

	public TKCriteria<A, B> orLike(boolean condition, Fn<A, B> fn, String value) {
		if (condition) {
			super.orLike(Reflections.fnToFieldName(fn), value);
		}
		return this;
	}

	@Override
	public TKCriteria<A, B> orNotLike(Fn<A, B> fn, String value) {
		super.orNotLike(Reflections.fnToFieldName(fn), value);
		return this;
	}

	public TKCriteria<A, B> orNotLike(boolean condition, Fn<A, B> fn, String value) {
		if (condition) {
			super.orNotLike(Reflections.fnToFieldName(fn), value);
		}
		return this;
	}

	public TKCriteria<A, B> then() {
		TKCriteria<A, B> andOr = (TKCriteria<A, B>) queryTK.createCriteria();
		queryTK.and(andOr);
		return andOr;
	}

	public TK<A> end() {
		return queryTK;
	}

}
